using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using Db4objects.Db4o;
using Db4objects.Db4o.Linq;

namespace SharedObjects
{
	[DataContract]
	[ReferencedBy(typeof(Gateway))]
	[ReferencedBy(typeof(Agent))]
	public class ComputerSystem : EntityBase
	{
		[DataMember]
		[Required]
		public string Name { get; set; }

		[DataMember]
		public double MapX { get; set; }
		[DataMember]
		public double MapY { get; set; }
		
		[DataMember]
		public double MaintenanceInterval { get; set; } //this gets divided by the difficulty level, ie. 1 minute / 5 -> 12 seconds

		[DataMember]
		public bool AlwaysInvisible { get; set; }

		[DataMember]
		public bool AlwaysVisible { get; set; }

		[DataMember]
		public bool IsGatewayCentral { get; set; }

		[DataMember]
		public bool IsDefaultEmailServer { get; set; }

		[DataMember]
		public bool IsDefaultBankServer { get; set; }

		[DataMember]
		public bool TrustedConnectionOnly { get; set; }

		[DataMember]
		public int DifficultyLevel { get; set; } //max 5, min 0.

		[DataMember]
		public List<ComputerSystemLog> ComputerSystemLogs { get; set; }

		[DataMember]
		[Required(RequiredType.AtLeastOne)]
		public List<ComputerSystemFeature> ComputerSystemFeatures { get; set; }

		[DataMember]
		public List<SecuritySystem> SecuritySystem { get; set; }
		
		[DataMember]
		[Required]
		public NetworkAddress NetworkAddress { get; set; } //1

		[DataMember]
		public SystemDirectory RootDirectory { get; set; }

		[DataMember]
		[Required(RequiredType.ExactlyOne)]
		public Corporation Corporation { get; set; } //1

		[DataMember]
		public List<ComputerSystemAccount> Accounts { get; set; }

		[DataMember]
		public SystemVisibility Visibility { get; set; }

		public string GetHostname()
		{
			return string.Format("{0}.{1}.{2}", Name.ToLower().Replace(" ", ""), Corporation.Name.ToLower().Replace(" ", ""), Corporation.TopLevelDomain.Name.ToLower());
		}

		/// <summary>
		/// creates an entry in a system's log.
		/// </summary>
		/// <param name="db">a reference to a database client</param>
		/// <param name="who">the connecting system</param>
		/// <param name="what">which action was performed</param>
		/// <param name="affectedItem">the name/whatever that identifies the affected item (filename, record id etc)</param>
		public void Log(IObjectContainer db, ulong? who, LoggingAction what, string affectedItem)
		{
			//ComputerSystem targetSystem = (from ComputerSystem cs in db where cs.ID == systemId select cs).FirstOrDefault();
			//if (targetSystem == null)
			//    return;
			ComputerSystemLog log = new ComputerSystemLog
			{
				Id = Extension.ToLong(Guid.NewGuid()),
				TimeStamp = DateTime.Now,
				Activity = what,
				ModifiedItem = affectedItem,
				LoggingComputerSystemId = Id
			};

			if (who != null)
			{
				ComputerSystem source = (from ComputerSystem cs in db where cs.Id == who.Value select cs).FirstOrDefault();
				if (source != null)
					log.ConnectingSystemAddress = source.NetworkAddress.ToString();
			}
			db.PersistEntity(log);
		}

		public static implicit operator SmallComputerSystem(ComputerSystem cs)
		{
			return new SmallComputerSystem
			{
				Corporation = cs.Corporation,
				Id = cs.Id,
				IsDeleted = cs.IsDeleted,
				MapX = cs.MapX,
				MapY = cs.MapY,
				Name = cs.Name,
				IsGatewayCentral = cs.IsGatewayCentral,
				AlwaysInvisible = cs.AlwaysInvisible
			};
		}
	}

	[DataContract]
	public class SmallComputerSystem : EntityBase
	{
		[DataMember] public string Name { get; set; }
		[DataMember] public double MapX { get; set; }
		[DataMember] public double MapY { get; set; }
		[DataMember] public Corporation Corporation { get; set; }
		[DataMember] public bool IsGatewayCentral { get; set; }
		[DataMember] public bool AlwaysInvisible { get; set; }
		//public static implicit operator SmallComputerSystem(ComputerSystem cs)
		//{
		//    return new SmallComputerSystem
		//    {
		//        Corporation = cs.Corporation, ID = cs.ID, IsDeleted = cs.IsDeleted, MapX = cs.MapX, MapY = cs.MapY, Name = cs.Name, IsGatewayCentral = cs.IsGatewayCentral,
		//        AlwaysInvisible = cs.AlwaysInvisible
		//    };
		//}
	}

	public enum SystemVisibility
	{
		Visible,
		LanVisible,
		AdminVisible,
		Invisible
	}
}